package com.jerei.plugin.control;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jerei.plugin.exceptions.PluginNotInstallException;
import com.jerei.web.plugin.api.IPluginConfig;
import com.jerei.web.plugin.controller.PluginController;
import com.jerei.web.utils.UtilsPluginManager;
import com.jerei.web.utils.UtilsPluginUpdateManager;
import com.jerei.web.utils.UtilsUI;
import com.jerei.web.utils.UtilsWeb;
import com.jerei.web.utils.spring.JrResourceBundleMessageSource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import ro.fortsoft.pf4j.Extension;
import ro.fortsoft.pf4j.PluginException;
import ro.fortsoft.pf4j.PluginWrapper;
import ro.fortsoft.pf4j.update.UpdateRepository;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by sunfeihu on 2016/11/25.
 */
@Extension
public class BaseControl extends PluginController {

    @RequiresPermissions("plugin-manage:view")
    public String start() throws PluginException {
        String pluginId = UtilsWeb.getString(this.getRequest(), "pluginId");
        UtilsPluginManager.get().startPlugin(pluginId);
        return UtilsUI.ok();
    }

    @RequiresPermissions("plugin-manage:view")
    public String stop() throws PluginException {
        String pluginId = UtilsWeb.getString(this.getRequest(), "pluginId");
        UtilsPluginManager.get().stopPlugin(pluginId);
        return UtilsUI.ok();
    }

    @RequiresPermissions("plugin-manage:remove")
    public String delete() throws PluginException {
        String[] ids = this.getRequest().getParameterValues("ids");
        if (null != ids && ids.length > 0) {
            for (String pluginId : ids) {
                UtilsPluginManager.get().deletePlugin(pluginId);
            }
        }
        //插件成功启动之后，需要更新国际化文件
        JrResourceBundleMessageSource.update = true;
        return UtilsUI.ok();
    }

    /**
     * 重新安装插件
     *
     * @return
     */
    @RequiresPermissions("plugin-manage:view")
    public String reUpload() throws PluginException, IOException {
        String pluginId = UtilsWeb.getString(this.getRequest(), "pluginId");
        //先删除插件
        UtilsPluginManager.get().deletePlugin(pluginId);
        //再调用上传插件方法
        this.upload();
        return UtilsUI.ok();
    }

    @RequiresPermissions("plugin-manage:view")
    public String upload() throws PluginException, IOException {
        File pluginFile = null;
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) this.getRequest();
        Iterator<String> iter = multipartRequest.getFileNames();
        MultipartFile file = null;
        while (iter.hasNext()) {
            file = multipartRequest.getFile((String) iter.next());
            if (file != null) {
                pluginFile = new File(this.getRequest().getSession().getServletContext().getRealPath("/admin/plugins") + File.separator + file.getOriginalFilename());
                file.transferTo(pluginFile);
            }
        }
        if (null != pluginFile) {
            //加载插件
            String pluginId = UtilsPluginManager.get().loadPlugin(pluginFile);
            if (null != pluginId) {
                //启动插件
                PluginWrapper pluginWrapper = UtilsPluginManager.get().getPlugin(pluginId);
                UtilsPluginManager.get().startPlugin(pluginId);
                //插件成功启动之后，需要更新国际化文件
                JrResourceBundleMessageSource.update = true;
            }
            return UtilsUI.ok();
        } else {
            return UtilsUI.fail();
        }
    }

    /**
     * 更新插件
     *
     * @return
     */
    @RequiresPermissions("plugin-manage:view")
    public String updatePlugin() throws IOException {
        String pluginId = UtilsWeb.getString(this.getRequest(), "pluginId");
        String url = UtilsWeb.getString(this.getRequest(), "url");
        UtilsPluginUpdateManager utilsPluginUpdateManager = new UtilsPluginUpdateManager(UtilsPluginManager.get());
        if (utilsPluginUpdateManager.updatePlugin(pluginId, url, this.getRequest().getServletContext().getRealPath("/admin/plugins"))) {
            //插件成功启动之后，需要更新国际化文件
            JrResourceBundleMessageSource.update = true;
            return UtilsUI.ok();
        }
        return UtilsUI.fail();
    }

    @RequiresPermissions("plugin-manage:view")
    public String all() {
        JSONObject obj = null;
        JSONArray arr = new JSONArray();
        List<PluginWrapper> plugins = UtilsPluginManager.get().getPlugins();
        for (PluginWrapper pluginWrapper : plugins) {
            obj = new JSONObject();
            obj.put("id", pluginWrapper.getPluginId());
            obj.put("state", pluginWrapper.getPluginState().toString());
            obj.put("version", pluginWrapper.getDescriptor().getVersion().getNormalVersion());
            arr.add(obj);
        }
        return arr.toJSONString();
    }

    @RequiresPermissions("plugin-manage:view")
    public String page() {
        List<PluginWrapper> plugins = UtilsPluginManager.get().getPlugins();
        JSONArray arr = new JSONArray();
        if (null != plugins && plugins.size() > 0) {
            JSONObject obj = null;
            Map<String, UpdateRepository.PluginInfo> pluginUpdate = new HashMap<String, UpdateRepository.PluginInfo>();
            UtilsPluginUpdateManager updateManager = new UtilsPluginUpdateManager(UtilsPluginManager.get());
            //获取可更新插件
            List<UpdateRepository.PluginInfo> updates = updateManager.getUpdates();
            for (UpdateRepository.PluginInfo plugin : updates) {
                pluginUpdate.put(plugin.id, plugin);
            }
            UpdateRepository.PluginInfo pluginInfo = null;
            UpdateRepository.PluginRelease pluginRelease = null;
            for (PluginWrapper pluginWrapper : plugins) {
                obj = new JSONObject();
                obj.put("id", pluginWrapper.getPluginId());
                obj.put("state", pluginWrapper.getPluginState().toString());
                obj.put("version", pluginWrapper.getDescriptor().getVersion().getNormalVersion());
                //如果有更新
                if (pluginUpdate.keySet().contains(pluginWrapper.getPluginId())) {
                    pluginInfo = pluginUpdate.get(pluginWrapper.getPluginId());
                    pluginRelease = pluginInfo.getLastRelease(updateManager.lastVersion(pluginInfo));
                    //获取最后更新
                    obj.put("update", pluginRelease);
                } else {
                    obj.put("update", null);
                }
                try {
                    UtilsPluginManager.getExtension(IPluginConfig.class, pluginWrapper.getPluginId());
                    obj.put("config", true);
                } catch (PluginNotInstallException e) {
                    obj.put("config", false);
                }
                arr.add(obj);
            }
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("total", plugins.size());
        jsonObject.put("rows", arr);
        return jsonObject.toJSONString();
    }

}